﻿package states {
	import astar.*;
	import flash.accessibility.AccessibilityImplementation;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.events.WeakFunctionClosure;
	import levels.Level;
	import org.flintparticles.threeD.renderers.controllers.mxml.FirstPersonCamera;
	import org.flixel.*;
	import org.flixel.data.*;
	import sprites.*;

	/**
	 * ...
	 * @author test
	 */
	public class LevelState extends FlxState {
		public var HUD_group:FlxGroup;
		public var _player:Player;
		public var cur_level:Level;
		public var next_level_id:String;
		public var ready:Boolean;
		public var fog:Fog;
		public var fps:FlxText;
		public var fires_loc:Array;
		public var path_finder:AStar;
		public var _sheeps:Sheeps;

		[Embed(source="../../bin/imgs/arrow.png")]
		public var ArrowGraphic:Class;
		public var arrow_spr:FlxSprite;
		static public var ARROW_DIS:uint = 30;

		/*
		   public var ebar_origi_len:uint;
		   public var energy_bar:FlxGroup;
		   public var ebar_back:FlxSprite;
		   public var ebar_front:FlxSprite;
		 */

		public function general_update():void {
			fps.text = FlxU.floor(1 / FlxG.elapsed) + " fps";

			FlxU.overlap(_player, cur_level._exit, handleExit);
			if (ready) {
				for each (var num:Number in cur_level._groups["collide"]){
					FlxU.collide(_player, cur_level._groups[num]);
					FlxU.collide(_sheeps, cur_level._groups[num]);
					//FlxU.collide(_player.weapon, cur_level._groups[num]);
				}
				/*
				   for each (var b:Bullet in _player.weapon.wballs){
				   if (b.exists){
				   for each (var gid:uint in cur_level._fire_obj_index){
				   FlxU.overlap(b, cur_level._obj_group.members[gid], handleHitFire);
				   }
				   //子彈碰樹樹～
				   for each (var index:Number in cur_level._groups["collide"]){
				   var p:FlxPoint = Fire.generalToTile(b.x, b.y);
				   if (cur_level._groups[index].members[0].getTile(p.x, p.y) == 3){
				   b.exists = false;
				   }
				 }*/ /*
				   }
				   }
				 */
				for each (var gid:uint in cur_level._fire_obj_index){
					FlxU.overlap(_player.weapon.wball_group, cur_level._obj_group.members[gid], handleHitFire);
				}

				//ebar_front.scale.x = (_player.weapon._energy / _player.weapon._menergy);

				arrow_spr.x = ARROW_DIS * Math.cos(_player.weapon.angle * Math.PI / 180) + _player.x;
				arrow_spr.y = ARROW_DIS * Math.sin(_player.weapon.angle * Math.PI / 180) + _player.y;
				arrow_spr.angle = _player.weapon.angle;

				FlxG.followBounds(0, 0, cur_level._groups[0].members[0].widthInTiles * 35, cur_level._groups[0].members[0].heightInTiles * 35, false);
				FlxG.follow(_player);
			}
		}

		public function handleHitFire(_b:Bullet, _f:FlxSprite):void {
			if (--_f.health == 0){
				_f.kill();
			}
			_b.exists = false;
			trace("Fire Hit! HP=", _f.health);
		}

		public function handleExit(_p:FlxObject, _e:FlxObject):void {
			trace("over exit", _p.x, _p.y);
			if (next_level_id != null){
				gotoLevel(next_level_id);
			}
		}

		public function LevelState(){
			super();
			ready = false;
		}

		public function gotoLevel(id:String):void {
			if (FlxG.state == this){
				ready = false;
				trace("gotoLevel");
				FlxG.levels[id]._state.load(id);
				FlxG.buffer = new BitmapData(FlxG.width, FlxG.height);
				FlxG.state = FlxG.levels[id]._state;
			}
		}

		public function load(id:String):void {
			set_level(id);
			set_path_finder(0, 3);
			set_player(cur_level._start.x, cur_level._start.y);
			set_sheeps();
			set_HUD(FlxG.width, 75, 0, FlxG.height - 75, 0x88ffffff);
			set_fog(200);
			set_fps()

			load_level();
			load_sheeps();
			load_player();
			load_fog();
			load_HUD();
			load_fps();

			ready = true;
			/*
			   var ff:FlxSprite = new FlxSprite();
			   ff.createGraphic(100, 100, 0x000000);
			   var t:FlxTilemap = cur_level._groups[cur_level._groups["collide"][0]].members[0];
			   path_finder = new AStar(t, 0, 3);
			   path_finder.start(Fire.generalToTile(_player.x, _player.y), new FlxPoint(t.widthInTiles - 2, t.heightInTiles - 2));
			   path_finder.print_path();
			   show_path(path_finder.path);
			 */

			trace("Level loaded");
		}

		public function show_path(_path:Array):void {
			for (var i:uint = 0; i < _path.length - 1; i++){
				cur_level._groups[cur_level._groups["path"]].members[0].setTile(_path[i].x, _path[i].y, 4 + AStar.chooseDir(_path[i], _path[i + 1]), true);
			}
		}

		public function set_fps():void {
			fps = new FlxText(FlxG.width - 40, 0, 40).setFormat(null, 8, 0xffffff, "right");
			fps.scrollFactor.x = fps.scrollFactor.y = 0;

		}

		public function load_fps():void {
			this.add(fps);
		}

		public function set_path_finder(_allow:uint, _denied:uint):void {
			var t:FlxTilemap = cur_level._groups[cur_level._groups["collide"][0]].members[0];
			path_finder = new AStar(t, _allow, _denied);
		}

		public function set_sheeps():void {
			this._sheeps = cur_level.sheeps;
			
			_sheeps._state = this;
			_sheeps.start();
		}

		public function load_sheeps():void {
			add(_sheeps);
		}

		public function set_player(_x:Number, _y:Number):void {
			_player = new Player(_x, _y);
			arrow_spr = new FlxSprite();
			arrow_spr.loadGraphic(ArrowGraphic);
		}

		public function load_player():void {
			this.add(_player);
			this.add(_player.weapon);
			this.add(arrow_spr);

			FlxG.followBounds(0, 0, 0, 0);
			FlxG.followAdjust(10, 10);
		}

		public function set_level(id:String):void {
			cur_level = FlxG.levels[id];

			fires_loc = new Array();
			for (var i:uint = 0; i < cur_level._groups[0].members[0].widthInTiles; i++){
				fires_loc[i] = new Array();
				for (var j:uint = 0; j < cur_level._groups[0].members[0].heightInTiles; j++){
					fires_loc[i][j] = new uint(Fire.NONE);
				}
			}
			for each (var gid:uint in cur_level._fire_obj_index){
				cur_level._obj_group.members[gid].fires_loc = this.fires_loc;
			}
		/*
		 *
		 * 設定火焰1/0矩陣
		 *
		 */ /*
		   FlxG.saves = new Array();
		   FlxG.saves["fires_loc"] = new Array();
		   var tt:FlxTilemap = FlxG.levels[cur_level._id]._groups[0].members[0];
		   for (var i:uint = 0; i < tt.widthInTiles; i++){
		   FlxG.saves["fires_loc"][i] = new Array();
		   for (var j:uint = 0; j < tt.heightInTiles; j++) {
		   FlxG.saves["fires_loc"][i][j] = new uint(Fire.NONE);
		   }
		   }
		 */
			 //trace("L E N G T H",FlxG.saves["fires_loc"][20].length);
		}

		public function load_level():void {
			var cid:String = cur_level._id;

			/*
			   for (var i:Number = 0; i < FlxG.levels[cid]._groups.length; i++){
			   if (FlxG.levels[cid]._groups[i] is FlxGroup){
			   this.add(FlxG.levels[cid]._groups[i]);
			   }
			   }
			 */
			for each (var o:*in FlxG.levels[cid]._groups){
				if (o is FlxGroup){
					this.add(o);
				}
			}
			for each (var gid:uint in cur_level._fire_obj_index){
				//trace(gid);
				cur_level._obj_group.members[gid].turnOn();
			}
		}

		public function hitWall(obj:FlxObject, _x:uint, _y:uint, tid:uint):void {
			trace("hitWall");
		}

		public function set_fog(size:uint):void {
			fog = new Fog(_player);
			fog.scrollFactor = new FlxPoint(0, 0);
		}

		public function load_fog():void {
			//this.add(fog);
		}

		public function set_HUD(_width:uint, _height:uint, _x:uint, _y:uint, _bgcolor:int):void {
			HUD_group = new FlxGroup();
			HUD_group.scrollFactor = new FlxPoint(0, 0);
			HUD_group.x = _x;
			HUD_group.y = _y;

			var HUD_bg:FlxSprite = new FlxSprite();
			HUD_bg.createGraphic(_width, _height, _bgcolor);

			var energy_bar:Bar = new Bar("Water", _player, 0xff0000ff, 100, 10, 10, 10);

			/*4
			   energy_bar = new FlxGroup();
			   ebar_back = new FlxSprite();
			   ebar_front = new FlxSprite();
			   var ene_txt:FlxText = new FlxText(0, 0, 100, "Water");
			   ebar_origi_len = new uint(100);

			   energy_bar.scrollFactor = new FlxPoint(0, 0);

			   ebar_back.createGraphic(ebar_origi_len, 20, 0xffffffff);
			   ebar_front.createGraphic(ebar_origi_len, 20, 0xff0000ff);
			   ebar_front.origin.x = 0;
			   ebar_back.x = ebar_front.x = 0;
			   ebar_back.y = ebar_front.y = 30;
			   ene_txt.setFormat(null, 12, 0xffffff, "center");

			   energy_bar.add(ebar_back, true);
			   energy_bar.add(ebar_front, true);
			   energy_bar.add(ene_txt, true);

			   energy_bar.x = 10;
			   energy_bar.y = 10;
			 */
			HUD_group.add(HUD_bg, true);
			HUD_group.add(energy_bar, true);
		}

		public function load_HUD():void {
			this.add(HUD_group);
		}
	}
}